package club.cearnach.api.service.impl;

import club.cearnach.api.annotation.CacheDeleteAll;
import club.cearnach.api.dao.IMovieTypeDao;
import club.cearnach.entity.MovieType;
import club.cearnach.api.exception.MovieException;
import club.cearnach.api.exception.MovieTypeException;
import club.cearnach.api.form.PageBean;
import club.cearnach.api.service.IMovieService;
import club.cearnach.api.service.IMovieTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

/**
 * @author 阮胜
 * @date 2018/5/12 13:43
 */
@Service
@CacheConfig(cacheNames = "MOVIE_TYPE_ENTITY")
@Transactional(rollbackFor = Exception.class)
public class MovieTypeServiceImpl implements IMovieTypeService {
    public static final String CACHE_MOVIE_TYPE_NAME = "CACHE_MOVIE_TYPE_NAME";
    public static final String CACHE_FIND_ALL = "CACHE_MOVIE_TYPE_FIND_ALL";
    private final IMovieTypeDao movieTypeDao;
    /**
     * 这里为了避免循环依赖,不能使用构造函数的方式注入,需要使用使用注解注入
     */
    @Autowired
    private IMovieService movieService;

    public MovieTypeServiceImpl(IMovieTypeDao movieTypeDao) {
        this.movieTypeDao = movieTypeDao;
    }


    @Override
    public Page<MovieType> findAll(Pageable pageable) {
        return movieTypeDao.findAll(pageable);
    }

    @Override
    public List<MovieType> findAll() {
        return movieTypeDao.findAll();
    }

    @CacheDeleteAll
    @Override
    public MovieType save(MovieType movieType) {
        Optional<MovieType> type = movieTypeDao.findByTypeName(movieType.getTypeName());
        return type.map(movieTypeDao::save)
                .orElseGet(() -> movieTypeDao.save(movieType));
    }

    @Cacheable(value = CACHE_MOVIE_TYPE_NAME, key = "'movie_type_'+#id")
    @Override
    public MovieType findById(Integer id) throws MovieTypeException {
        return movieTypeDao.findById(id).orElseThrow(() -> new MovieTypeException(MovieTypeException.MOVIE_TYPE_CAN_NOT_FOUND));
    }

    @CacheDeleteAll
    @Override
    public void delete(Integer id) throws MovieTypeException {
        movieTypeDao.findById(id).orElseThrow(() -> new MovieTypeException(MovieTypeException.MOVIE_TYPE_CAN_NOT_FOUND));
        movieService.findByTypeId(id).forEach(movie -> {
            try {
                movieService.delete(movie.getId());
            } catch (MovieException e) {
                e.printStackTrace();
            }
        });
        movieTypeDao.deleteById(id);

    }

    @CacheDeleteAll
    @Override
    public void deleteIn(Integer[] idArr) {
        for (int id : idArr) {
            try {
                delete(id);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Cacheable(value = CACHE_FIND_ALL, key = "'findAllOrderByCreateDate_'+#pageBean.getPage()+'_'+#pageBean.getSize()")
    @Override
    public Page<MovieType> findAllOrderByCreateDate(PageBean pageBean) {
        return movieTypeDao.findAll(PageRequest.of(pageBean.getPage(), pageBean.getSize(), Sort.by(Sort.Direction.DESC, "createDate")));
    }

    @Override
    public long count() {
        return movieTypeDao.count();
    }


    @Override
    public boolean isExist(Integer id, String typeName) {
        return id == 0
                ? movieTypeDao.findByTypeName(typeName).isPresent()
                : movieTypeDao.findByTypeNameAndIdNot(typeName, id).isPresent();

    }

    @Override
    public boolean isExist(MovieType movieType) {
        return isExist(movieType.getId(), movieType.getTypeName());
    }
}